package biopepa;

import java.io.*;
import java.util.*;

import biopepa.mainParser.*;

public class BiopepaModel {
		
    public HashMap<String , NewLocation> locationObjects;
    public boolean hasLocations;
    public boolean hasOneLocation;
	public HashMap<String , NewSpecies> speciesList;
	public HashMap<String , NewParameter > parameterObjects;
	public HashMap<String , NewParameter > parameterObjects2;
	public HashMap<String , NewLaw > lawObjects;
	public HashMap<String , NewLaw > lawObjectsEff;
	public HashMap<String , ActionEnabled > actionObjects;
	public HashMap<String , NewCompositionalDef> compositionalDefObjects;
	public HashMap<String , NewReaction> cooperations;
	public HashMap<String , NewReaction> cooperations2;
	
	public simhya.matheval.Evaluator valutatore; 
	
	public HashMap<String , Automaton> automatonObjects;
	public HashMap<String , Automaton> automatonObjects2;
	public Automaton rateAutomaton;
	public Automaton finalAutomaton;
	
	public HashMap<String , Node> nodeList;
	public Node rootNode;
	
	public BiopepaModel(){
		locationObjects = new HashMap<String , NewLocation>();
		hasLocations = false;
		hasOneLocation = true;
		parameterObjects = new HashMap<String , NewParameter >();
		parameterObjects2 = new HashMap<String , NewParameter >();
		lawObjects = new HashMap<String , NewLaw> ();
		lawObjectsEff = new HashMap<String , NewLaw> ();
		actionObjects = new HashMap<String , ActionEnabled> ();
		speciesList = new HashMap<String , NewSpecies>();
		compositionalDefObjects = new  HashMap<String , NewCompositionalDef> ();
		cooperations = new HashMap<String , NewReaction>();
		cooperations2 = new HashMap<String , NewReaction>();
		automatonObjects = new HashMap<String , Automaton> ();
		automatonObjects2 = new HashMap<String , Automaton> ();
		rateAutomaton = new Automaton("rate");
		finalAutomaton = new Automaton("Final automaton");
		nodeList = new HashMap<String , Node>();
		rootNode=null;
		valutatore = new simhya.matheval.Evaluator();
		
		//Add default location
		NewLocation defaultLocation;
		defaultLocation = addLocation("main");
		defaultLocation.locationSize=1;

	}
	
	
	
	//Metodo da chiamare
	
	public String loadBiopepa(String fileName){
		Annino annino = new Annino( this , valutatore); 
		try{
			annino.parseFromFile(fileName);
		}
		catch(Exception e){
			throw new BiopepaException(e.getMessage());
		}
		catch(Error e){
			throw new BiopepaException(e.getMessage());
		}
		
		runParser(valutatore);
        finalCheck();
        addInfo2();      
		createTree();
		createAutomata();
		return automatonString(finalAutomaton);
	}

	
	
	
	
	//*****PARSING MATH EXPRESSIONS*****
	
	public void runParser(simhya.matheval.Evaluator evaluator) {
		valutatore = evaluator;	
		
		//Verifico se sono parametri o espressioni
		
		ArrayList<String> list1 = new ArrayList<String>();
		list1 = valutatore.getNameOfAllVariables();	
		int size1= list1.size();
		
		Iterator iterator5 = parameterObjects.keySet().iterator();  		   
		while (iterator5.hasNext()) {  
			String key = iterator5.next().toString();  
			int l;
			int id = parameterObjects.get(key).parserId;
			 for(l=0; l<size1; l++){
					 if(valutatore.getExpression(id).containsSymbol(list1.get(l)) == true){
						 parameterObjects.get(key).isExpression = true;
					 }
				 }
		} 
	
		
		//Parso le kinetic law
		
		Iterator iterator4 = lawObjects.keySet().iterator();  		   
		while (iterator4.hasNext()) {  
		   int id;	
		   String key = iterator4.next().toString();  
		   try{
			   id = valutatore.parse(lawObjects.get(key).lawExpression);
		   }
		   catch(Exception e) {
			   throw new BiopepaException("Problem in kinetic law definition of'" + lawObjects.get(key).lawOf + "': '" + lawObjects.get(key).lawExpression + "'.");
		   }
		}
		


		
		//Output
		
		ArrayList<String> allConstants; 
		allConstants = valutatore.getNameOfAllConstants();	
		int constantsSize = allConstants.size();
		for(int i=0 ; i< constantsSize; i++){
			//System.out.println("Aggiunto parametro: " + allConstants.get(i));
		}
		
		ArrayList<String> allVariables; 
		allVariables = valutatore.getNameOfAllVariables();	
		int variablesSize = allVariables.size();
		for(int i=0 ; i< variablesSize; i++){
			//System.out.println("Aggiunto variabile: " + allVariables.get(i));
		}	
		
	}
	
	
	
	
	
	

	
	
	//*****STANDARD METHODS*****
	

	
	public NewLocation addLocation(String name){
		  NewLocation newLoc;
		  newLoc = new NewLocation(name , this);
		  newLoc.locationSize = 0;
		  locationObjects.put(newLoc.locationName , newLoc);
		  return newLoc;
		}
	
	public void addSpecies(String name){
		NewSpecies newSpec;
		newSpec = new NewSpecies(name);
		newSpec.speciesUpper = 0;
		newSpec.hasComponent = false;
		speciesList.put(name , newSpec);
		}
		
	public void addParameter(String name , String expression){
		NewParameter newParam;
		newParam = new NewParameter(name , expression);
			  parameterObjects.put(name , newParam);
		}
	
	public void addLaw(String name , String expression){
		NewLaw newLaw;
		newLaw = new NewLaw(name , expression ,this);
		  lawObjects.put(name , newLaw);
		}
	
	public void addLaw(String name ){
			NewLaw newLaw;
			newLaw = new NewLaw(name , this);
			  lawObjects.put(name , newLaw);	
		}
	
	public void addAction(String name){
		ActionEnabled newAction;
		newAction = new ActionEnabled(name , "0", "0");
		  actionObjects.put(name , newAction);
		}
	
	public void addCompositionalDef(String name){
		NewCompositionalDef newComp;
		newComp = new NewCompositionalDef(name);
		compositionalDefObjects.put(name , newComp);
	}
	
	public void addCooperations(ArrayList<ActionEnabled> actionList ){
		int i;
		int actionListSize = actionList.size();
		for(i=0; i< actionListSize; i++){
			NewReaction newReaction = new NewReaction(actionList.get(i).actionEnabledName );
			cooperations.put(actionList.get(i).actionEnabledName , newReaction);
			}
	}
	
	public NewLocation getLocation(String name){  
		return locationObjects.get(name);
	}
	
	public NewSpecies getSpecies(String name){
		return speciesList.get(name);
	}
	
	public NewParameter getParameter(String name){
		return parameterObjects.get(name);
	}
	
	public NewCompositionalDef getCompositionalDef(String name){
		return compositionalDefObjects.get(name);
	}
	
	public void setRoot(Node newRoot){
		rootNode = newRoot;
	}
	
	public boolean isLocation(String name) {
        return locationObjects.containsKey(name);
    }
	
	public boolean isParameter(String name) {
        return parameterObjects.containsKey(name);
    }
	
	public boolean isLaw(String name) {
        return lawObjects.containsKey(name);
    }
	
	public boolean isAction(String name) {
        return actionObjects.containsKey(name);
    }
	
	public boolean isSpecies(String name) {
	    return speciesList.containsKey(name);
	}
	
	public boolean isCompositionalDef(String name) {
        return compositionalDefObjects.containsKey(name);
    }
	
	public void removeMain(){
		locationObjects.remove("main");
	}
	
	public boolean isNode(String name) {
        return nodeList.containsKey(name);
    }
	
	public boolean isRoot(String name) {
		boolean bool;
		if(rootNode.getContent().nodeName == name)
			{bool = true;}
		else
			{bool = false;}
        return bool;
    }
	
	
	
	
	
	
	//*****CHECKS*****

	//Controllo1: Aggiunge la location nel caso in cui non sia presente
	
	public void locationCheck1(String location){
	      if(isLocation(location) == true)
		  {}
		 else{ 
		     addLocation(location);
		  }
	}
	
	public void locationCheck1b(NewLocation location){
	      if(isLocation(location.locationName) == true)
		  {}
		 else{ 
		     locationObjects.put(location.locationName , location);
		  }
	}
	
	
	public void locationCheck2(String location){
		if((isLocation(location) == true) && (getLocation(location).locationSize != 0) ){
			throw new BiopepaException("Multiple definition for location '" + getLocation(location).locationName + "'.");
	        }
		else if((isLocation(location) == true) && (getLocation(location).locationSize == 0))
		{   }
	    else{  
	       NewLocation newLocation;
		   newLocation = new NewLocation(location , this);
		   if(this.locationObjects.size() == 0){
			   newLocation.isFirstLocation = true;
		   }
		   locationObjects.put(location , newLocation);
		   NewParameter param1 = new NewParameter(newLocation.stepSizeVariableC , newLocation.locationStepSize);
		   NewParameter param2 = new NewParameter(newLocation.stepSizeVariableD , newLocation.locationStepSize);
		   param1.isStepSize = true;
		   param2.isStepSize = true;
//		   param1.paramNumber =1;
//		   param2.paramNumber =1;
		   parameterObjects.put(newLocation.stepSizeVariableC, param1);
		   parameterObjects.put(newLocation.stepSizeVariableD, param2);
		   //System.out.println("agg param " + param1.parameterName + "con exp " + param1.parameterExpression);
		   //System.out.println("agg param " + param2.parameterName + "con exp " + param2.parameterExpression);
		   }
		}	
		
	//Controllo1: Aggiunge la specie nel caso in cui non sia presente
	
	public void speciesCheck1(String name){
		if(isSpecies(name) == true)
		{}
		else{ 
			addSpecies(name);
		}
	}
	
	//Controllo1b: Aggiunge la specie nel caso in cui non sia presente
	
	public void speciesCheck1b(SpeciesAndLocations  speciesAndLocations){
		if(speciesAndLocations.hasLocations == true){
			if(isSpecies(speciesAndLocations.species)==false){
				addSpecies(speciesAndLocations.species);
			}
				NewSpecies species =getSpecies(speciesAndLocations.species);
				int i;
				int size = speciesAndLocations.locations.size();
				for(i=0; i<size; i++){
					LocationAndInitial location = speciesAndLocations.locations.get(i);
					locationCheck1b(location.location);
					species.addLocationsAccessible(location);
				}
		}
		else{
			if(isSpecies(speciesAndLocations.species) == false){
				addSpecies(speciesAndLocations.species);
			}
		}
			
	}
	
	//Controllo2b: Controlla che non ci siano pi� definizioni per la stessa specie
	
		public void speciesCheck2b(SpeciesAndLocations  speciesAndLocations){			
			if(isSpecies(speciesAndLocations.species) == false){
				addSpecies(speciesAndLocations.species); 
			}			
			if(speciesAndLocations.hasLocations == true ){
				int i;
				int size = speciesAndLocations.locations.size();
				for(i=0; i<size; i++){
					 LocationAndInitial locationAndInitial = speciesAndLocations.locations.get(i);
					 if( getSpecies(speciesAndLocations.species).locationsAccessible.get(locationAndInitial) == null){
						 getSpecies(speciesAndLocations.species).addLocationsAccessible(locationAndInitial);
					 	}
					 else{
						 if( getSpecies(speciesAndLocations.species).locationsAccessible.get(locationAndInitial).upper !=0){ 						
							    throw new BiopepaException("Multiple definition for species '" + speciesAndLocations.species + "'.");
							}
						 else{
							 getSpecies(speciesAndLocations.species).locationsAccessible.get(locationAndInitial).upper = locationAndInitial.upper;
						 }
					 }
				}
			}
			else{
				if(isSpecies(speciesAndLocations.species) == true){ 
					if(getSpecies(speciesAndLocations.species).speciesUpper != 0){
						throw new BiopepaException("Multiple definition for species '" + speciesAndLocations.species + "'.");
					}
					else{}			
					}
				else
				{  addSpecies(speciesAndLocations.species); }
			}	
		}
	
	//Controllo3: Controlla che non ci siano pi� componenti per la stessa specie
	
	public void speciesCheck3(String name){
		if(isSpecies(name) == true){ 
			if(getSpecies(name).hasComponent == true){
				throw new BiopepaException("Multiple component definition for species '" + getSpecies(name).speciesName + "'.");
			}
			else{}
			}
		else{ 
			addSpecies(name);}
	}
	
	//Controllo4: Controlla che tutte le specie presenti nella comp modello abbiano species component e upper
	
			public void speciesCheck4(String name){
				if(isSpecies(name) == false){
					throw new BiopepaException("Species '" + name + "' in model component is undefined.");
				}
				if(getSpecies(name).hasComponent == false){
					throw new BiopepaException("No species component for '" + name + "'.");
				}
				if(getSpecies(name).speciesUpper != 0){ 
				 }
				else{  
					throw new BiopepaException("Species '" + name + "' in model component is undefined.");
				 }				
			}
	
	//Controllo4b: Controlla che tutte le specie presenti nella comp modello abbiano species component e upper poi aggiunge initial
	
		public void speciesCheck4b(SpeciesAndLocations  speciesAndLocations){
				if(isSpecies(speciesAndLocations.species) == false){
					throw new BiopepaException("Species '" + speciesAndLocations.species+ "' in model component is undefined.");
				}
				if(getSpecies(speciesAndLocations.species).hasComponent == false){
					throw new BiopepaException("No species component for '" + speciesAndLocations.species+ "'.");
				}
				
					int i;
					int size = speciesAndLocations.locations.size();
					//System.out.println("model component " + size + " " + speciesAndLocations.species);
					for(i=0; i<size; i++){				
						LocationAndInitial loc = speciesAndLocations.locations.get(i);		
						String locName = loc.location.locationName;	
						if(getSpecies(speciesAndLocations.species).locationsAccessible.get(locName) == null){
							throw new BiopepaException("Error in model component: location '" + locName + "' is not accessible for species '" + speciesAndLocations.species+ "'.");
						}
						if(getSpecies(speciesAndLocations.species).locationsAccessible.get(locName).upper == 0){ 
							throw new BiopepaException("Undefined upper value for species '" + speciesAndLocations.species+ "' in location '" + locName + "'.");
						 }
						if(getSpecies(speciesAndLocations.species).locationsAccessible.get(locName).initial != -1){ 
							getSpecies(speciesAndLocations.species).locationsAccessible.get(locName).initial = loc.initial;
						 }
						else{  
							throw new BiopepaException("Initial value already definde for species '" + speciesAndLocations.species+ "'.");
						 }
					}
					
		}
	
	//Controllo1: Aggiunge la compositional def nel caso in cui non sia presente
	
	public void compositionalDefCheck1(String name){
	      if(isCompositionalDef(name) == true)
		  { }
		 else{ 
			 addCompositionalDef(name);
		   }
	}
	
	//Controllo2: Controlla che non ci siano pi� definizioni per la stessa compositional def

	public void compositionalDefCheck2(String name){
	      if((isCompositionalDef(name) == true) && (getCompositionalDef(name).hasDefinition == true) ){ 
	    	  throw new BiopepaException("Multiple definition for labelled compositional definition '" + getCompositionalDef(name).compositionalDefName + "'.");
	      }
	      else if((isCompositionalDef(name) == true) && (getCompositionalDef(name).hasDefinition == false)){
	    	  getCompositionalDef(name).hasDefinition = true;
	      }
		 else{ 
			 addCompositionalDef(name);
		   }
	}
	
	//Controllo3: Controlla che tutte le compositional def presenti nella comp modello siano definite
	
	public void compositionalDefCheck3(String name){
	      if(isCompositionalDef(name) == true)
		  { }
		 else{ 
			 throw new BiopepaException("Labelled compositional definition '" + name + "' in model component is undefined.");
		   }
	}
	
	//Controllo4: Controlla che non ci siano loop nelle compositional def
	
		public void compositionalDefCheck4(String name){
		      if(isCompositionalDef(name) == false ){
		    	  addCompositionalDef(name);
			      getCompositionalDef(name).isCalled = true;
			      }
		      else if((isCompositionalDef(name) == true) && (getCompositionalDef(name).isCalled == true)){
		    	  throw new BiopepaException("Error: loop for labelled compositional definition '" + name + "'.");
			      }
			  else if((isCompositionalDef(name) == true) && (getCompositionalDef(name).isCalled == false)){  
				  getCompositionalDef(name).isCalled = true; 
				  }
		}
	
	//Controllo: Controlla che non ci siano pi� definizioni per lo stesso parametro
	
	public void parameterCheck(String name , String expression){
		if(isParameter(name) == true){
			throw new BiopepaException("Multiple definition for parameter '" + name + "'.");
		    }
		else{  
			NewParameter newParameter;
		    newParameter = new NewParameter(name , expression);
//		    newParameter.paramNumber = 2;
			parameterObjects.put(name , newParameter);}
			}
	
	//Controllo1: Controlla che non ci siano pi� definizioni per la stesse reazione
			
	public void lawCheck1(String name , String expression){
		      if(isLaw(name) == true && lawObjects.get(name).lawExpression != null){
		    	  throw new BiopepaException("Multiple definition for kinetic law of '" + name + "'.");
		      }
		      else if(isLaw(name) == true && lawObjects.get(name).lawExpression == null){
		    	  lawObjects.get(name).lawExpression = expression;
		      }
		      else if(isLaw(name) == false){  
		    	  addLaw( name , expression );	    	  
			  }
			}	
	
	//Controllo1b: Controlla che non ci siano pi� definizioni per la stesse reazione per fMA 
	
		public void lawCheck1b(NewLaw law){
			      if(isLaw(law.lawOf) == true && lawObjects.get(law.lawOf).lawExpression != null){
			    	  throw new BiopepaException("Multiple definition for kinetic law of '" + law.lawOf + "'.");
			      }
			      else if(isLaw(law.lawOf) == true && lawObjects.get(law.lawOf).lawExpression == null){
			    	  lawObjects.get(law.lawOf).lawExpression = law.lawExpression;
			    	  lawObjects.get(law.lawOf).isFMA = law.isFMA;
			    	  lawObjects.get(law.lawOf).isFMM = law.isFMM;		
			    	  lawObjects.get(law.lawOf).parameter1 = law.parameter1;
			    	  lawObjects.get(law.lawOf).parameter2 = law.parameter2;
			      }
			      else if(isLaw(law.lawOf) == false){  
			    	  lawObjects.put(law.lawOf, law);	    	  
				  }
				}
	
	//Controllo2: Aggiunge la legge nel caso in cui non sia presente e mette used
	
	public void lawCheck2(String name){
		if(isLaw(name) == true) {
			lawObjects.get(name).isUsed = true;
			}
	    else{
	    	addLaw(name);
		    }
		}		
	
	//Controllo1: Aggiunge l'azione nel caso in cui non sia presente
			
	public void actionCheck1(String name){
		      if(isAction(name) == true)
			  {}
			  else{
				  addAction(name);}
			  }	
	
	//Controllo2: Controlla che l'azione non sia chiamata pi� volte nelle compositional def e model component
	
		public void actionCheck2(ArrayList<ActionEnabled> actionList){
			int i;
			int actionListSize = actionList.size();
			for(i=0; i< actionListSize; i++){
				String name=actionList.get(i).actionEnabledName;
				if(isAction(name) == true){
				}
				else if(actionList.get(i).actionEnabledName.equals("*")){}
				else{ 
					 addAction(name);
				   }
				}
				     
			}
	
	//Controllo3:  Controlla che tutte le azioni presenti nella comp modello siano definite 
		//tolto: e verifica che non siano gi� state chiamate

	public void actionCheck3(ArrayList<ActionEnabled> actionList){
		int i;
		int actionListSize = actionList.size();
		for(i=0; i< actionListSize; i++){
			String name=actionList.get(i).actionEnabledName;
			if(isAction(name) == true){
			}
			else if(name.equals("*")){}
			else{ 
				throw new BiopepaException("Action '" + actionList.get(i).actionEnabledName + "' in model component is undefined.");
			   }
			}
		}	
	
	//Controllo: Controlla che i nomi delle due specie siano uguali
	
	public void sameSpeciesCheck(String name1, SpeciesAndAction speciesAndAction){
		if(speciesAndAction.operator == 6 || speciesAndAction.operator == 7){
			if(name1.equals(speciesAndAction.species))
			  { }
			 else{ 
				 throw new BiopepaException("Error: identifier in the species component '" + name1 + "' must be the species name.");
			   }
		}
		else{
			if(name1.equals(speciesAndAction.species))
			  { }
			 else{ 
				 throw new BiopepaException("Error: identifier in the species component '" + name1 + "' must be the species name.");
			   }
		}
	}
	
	
	//NON FUNZIONA
	//Controllo che le compositional def siano inserite nell'ordine giusto (verifico che un nodo non sia gi� stato inserito)
	public void nodeCheck(Node node){
	      if(nodeList.containsKey(node.getContent().nodeName) == false){ 
	    	  nodeList.put(node.getContent().nodeName , node);
	      }
	      else if(nodeList.containsKey(node.getContent().nodeName) == true && nodeList.get(node.getContent().nodeName).hasChildren() != node.hasChildren()){ //perch� potrebbe essere che una componente e una specie abbiano lo stesso nome
	    	  nodeList.put(node.getContent().nodeName , node);
	      }
		 else{ 
			 throw new BiopepaException("Error: labelled definitional component '" + node.getContent().nodeName + "' already used.");
		   }
	}
	
	//Verifica se due  arrayList di location sia disgiunti
	
	public boolean disjointLocationArrayCheck(ArrayList<NewLocation> array1, ArrayList<NewLocation> array2){
		boolean areDisjoint;
		areDisjoint=true;
		int size1 = array1.size();
		int size2 = array2.size();
		int i;
		for(i=0; i<size1; i++){
			int j=0;
			for(j=0; j<size2; j++){
				if(array1.get(i).locationName.equals(array2.get(j).locationName)){
					areDisjoint=false;
				}
			}
		}
		return areDisjoint;
	}
	
	
	//Controllo finale

	public void finalCheck(){
		
		//Controllo che le location abbiano la size definita
	     Iterator iterator1 = locationObjects.keySet().iterator();  		   
			while (iterator1.hasNext()) {  
			   String key = iterator1.next().toString();  
			   if(locationObjects.get(key).locationSize == 0){
				   throw new BiopepaException("Error: size undefined for location '" + locationObjects.get(key).locationName + "'.");
			   }		      
			}
			
		//Controllo che le species abbiano upper e initial definiti
			if(this.hasLocations == true){
				Iterator iterator = speciesList.keySet().iterator();  
				while (iterator.hasNext()) {  	
				   String key = iterator.next().toString();
				   Iterator iterator2 = speciesList.get(key).locationsAccessible.keySet().iterator();
				   while (iterator2.hasNext()){
					   String key2 = iterator2.next().toString();
					   if(speciesList.get(key).locationsAccessible.get(key2).upper == 0){
						   throw new BiopepaException("Error: undefined upper value for species '" + speciesList.get(key).speciesName + "'in location '" + speciesList.get(key).locationsAccessible.get(key2).location.locationName + "'.");
					   }
					   if(speciesList.get(key).locationsAccessible.get(key2).initial == -1){
						   throw new BiopepaException("Error: undefined intial value for species '" + speciesList.get(key).speciesName + "'in location '" + speciesList.get(key).locationsAccessible.get(key2).location.locationName + "'.");
					   }
				   }				   
				}
			}
			else{
				Iterator iterator2 = speciesList.keySet().iterator();  
				while (iterator2.hasNext()) {  	
				   String key = iterator2.next().toString();
				   if(speciesList.get(key).speciesUpper == 0){
					   throw new BiopepaException("Error: undefined upper value for species '" + speciesList.get(key).speciesName + "'.");
				   }
				   if(speciesList.get(key).speciesInitial == -1){
					   throw new BiopepaException("Error: undefined initial value for species '" + speciesList.get(key).speciesName + "'.");
				   }
				}
			}	
	}
	
	
	
	
	
	
	
	
	
	//PRIMA MODEL COMPONENT
	
	
	
	public void addInfo1(simhya.matheval.Evaluator evaluator){		
		
		//set hasOneLocation
		if(this.hasLocations == true){
			int size =locationObjects.size();
			if(size == 1){
				this.hasOneLocation = true;
			}
		}
		
		//Aggiunge le variabili step-size nel caso no locations
		if(this.hasLocations == false){
			   NewParameter param1 = new NewParameter("h.C" , 1);
			   NewParameter param2 = new NewParameter("h.D" , 1);
			   param1.isStepSize = true;
			   param2.isStepSize = true;
			   parameterObjects.put("h.C", param1);
			   parameterObjects.put("h.D", param2);
		}
		
		Iterator iterator2 = speciesList.keySet().iterator();  
		while (iterator2.hasNext()) {  	
		   String key = iterator2.next().toString();
			   
			//Aggiungo location alle species definite ovunque allo stesso modo e set initial value
			if(this.hasOneLocation == true){
				Iterator iterator2a = locationObjects.keySet().iterator();			   
			    while (iterator2a.hasNext()){
			    	String key2 = iterator2a.next().toString();
				    speciesList.get(key).addLocationsAccessible(locationObjects.get(key2));					     
					} 
			    Iterator iterator2b = speciesList.get(key).locationsAccessible.keySet().iterator();			   
			    while (iterator2b.hasNext()){
			    	String key2 = iterator2b.next().toString();
			    	speciesList.get(key).locationsAccessible.get(key2).upper = speciesList.get(key).speciesUpper;					     
					} 			    
			}
	          
			
		   
		   //Moltiplico il valore iniziale per lo step-size 
		   Iterator iterator2b = speciesList.get(key).locationsAccessible.keySet().iterator();			   
		   while (iterator2b.hasNext()){
			   String key2 = iterator2b.next().toString();
//			   speciesList.get(key).locationsAccessible.get(key2).initial = speciesList.get(key).locationsAccessible.get(key2).initial * speciesList.get(key).locationsAccessible.get(key2).location.locationStepSize;			  
		   }

		}
		
		//Aggiungo le location nelle action enabled per ogni specie
		Iterator iterator3 = speciesList.keySet().iterator();  
		while (iterator3.hasNext()) { 
			String key = iterator3.next().toString();
			Iterator iterator3a = speciesList.get(key).getActionsEnabledObjects().keySet().iterator(); 
			while (iterator3a.hasNext()) { 				
				String key2 = iterator3a.next().toString();
				if(speciesList.get(key).getActionsEnabledObjects().get(key2).locations == null){				
					speciesList.get(key).getActionsEnabledObjects().get(key2).locations = locationObjects;
//					System.out.println("species " + speciesList.get(key).speciesName + "  "  + locationObjects);
				}
				}
			}
		
		//controllo che la location di ogni action enabled sia effettivamente accessibile
		if(this.hasLocations == true){
			Iterator iterator4 = speciesList.keySet().iterator();  
			while (iterator4.hasNext()) { 
				String key = iterator4.next().toString();
				Iterator iterator4a = speciesList.get(key).getActionsEnabledObjects().keySet().iterator(); 
				while (iterator4a.hasNext()) { 				
					String key2 = iterator4a.next().toString();
					Iterator iterator4b = speciesList.get(key).getActionsEnabledObjects().get(key2).locations.keySet().iterator(); 
					while (iterator4b.hasNext()) { 				
						String key3 = iterator4b.next().toString();
						NewLocation location = speciesList.get(key).getActionsEnabledObjects().get(key2).locations.get(key3);
								if(speciesList.get(key).locationsAccessible.containsKey(location.locationName)==false){				
									throw new BiopepaException("Error in species component: location '" + location.locationName + "' is not accessible for species '" + speciesList.get(key).speciesName +"' .");
								}
					}					
					}
				}
		}
		
		
		// definisco lawObjectsEff
		Iterator iterator6 = lawObjects.keySet().iterator();  
		while (iterator6.hasNext()) { 
			String key = iterator6.next().toString();
			Iterator iterator6a = speciesList.keySet().iterator();  
			while (iterator6a.hasNext()) { 
				String key2 = iterator6a.next().toString();
				if(speciesList.get(key2).isActionEnabled(lawObjects.get(key).lawOf)){
						ActionEnabled action = speciesList.get(key2).getActionEnabled(lawObjects.get(key).lawOf);
						Iterator iterator6b = action.locations.keySet().iterator();  
						while (iterator6b.hasNext()) { 
							String key3 = iterator6b.next().toString();
							NewLocation loc = speciesList.get(key2).getActionEnabled(lawObjects.get(key).lawOf).locations.get(key3);
							lawObjects.get(key).location = loc;
							String nameWithLoc = lawObjects.get(key).lawOf + "." + loc.locationName;
							if(lawObjectsEff.containsKey(nameWithLoc) == false){
								lawObjectsEff.put(nameWithLoc , lawObjects.get(key));
								lawObjectsEff.get(nameWithLoc).lawOfwithLoc = nameWithLoc;
								lawObjectsEff.get(nameWithLoc).location = loc;
							    //System.out.println("agg " + nameWithLoc + " in " + lawObjectsEff.get(nameWithLoc).lawExpression);
							}
						}
				}
			}
		}
		
		//Sostituisco le fMA e le fMM con le relative espressioni
		Iterator iterator1 = lawObjectsEff.keySet().iterator();  
		while (iterator1.hasNext()) {  	
		   String key = iterator1.next().toString();
		   NewLaw law = lawObjectsEff.get(key);
		   if(lawObjectsEff.get(key).isFMM == true){
			   
			   Iterator iterator1a = speciesList.keySet().iterator();
			   while(iterator1a.hasNext()){
				   String key2 = iterator1a.next().toString();
				   if(speciesList.get(key2).isActionEnabled(law.lawOf)==true && speciesList.get(key2).getActionEnabled(law.lawOf).operator == 1  ){
					   law.reactant = speciesList.get(key2);
				   }
				   if(speciesList.get(key2).isActionEnabled(law.lawOf)==true && speciesList.get(key2).getActionEnabled(law.lawOf).operator == 2 ){
					   law.product = speciesList.get(key2);
				   }
				   if(speciesList.get(key2).isActionEnabled(law.lawOf)==true && speciesList.get(key2).getActionEnabled(law.lawOf).operator == 3 ){
					   law.enzime = speciesList.get(key2);
				   }
			   }
			   
			   if(law.reactant == null){
				   throw new BiopepaException("No reactant for fMM.");
			   }
			   if(law.product == null){
				   throw new BiopepaException("No product for fMM.");
			   }
			   if(law.enzime == null){
				   throw new BiopepaException("No enzime for fMM.");
			   }
			   
			   if(this.hasLocations == true && this.hasOneLocation == false){
				   law.lawExpression = law.parameter1 + "*" + law.reactant.speciesName  + "."+ law.location.locationName +"*"+ law.enzime.speciesName+ "." + law.location.locationName +"/"+ "(" + law.parameter2  +"+"+  law.reactant.speciesName+ "." + law.location.locationName + ")"; 
			   }
			   else{
				   law.lawExpression = law.parameter1 + "*" + law.reactant.speciesName  +"*"+ law.enzime.speciesName +"/"+ "(" + law.parameter2  +"+"+  law.reactant.speciesName+ ")"; 
			   }
			   
		   } 
		   else if(law.isFMA == true){
			   Iterator iterator1b = speciesList.keySet().iterator();
			   while(iterator1b.hasNext()){
				   String key2 = iterator1b.next().toString();
				   if(speciesList.get(key2).isActionEnabled(law.lawOf)==true){
					   int num = speciesList.get(key2).getActionEnabled(law.lawOf).operator;
					   if(num == 1 || num == 3 || num == 5  ){
						   if(law.reactsAndMods.contains(speciesList.get(key2))==false){
							   law.reactsAndMods.add(speciesList.get(key2));
							   law.stoichs.add(speciesList.get(key2).getActionEnabled(law.lawOf).stoichiometry);
						   }
					   }
					   else if(num == 4 || num == 6 || num == 7 ){
						   throw new BiopepaException("Species '" + speciesList.get(key2).speciesName +"' can't be involved in reaction '" + law.lawOf + "'.");
					   }
					   else{}
					   
				   }
			   }
			   
			   law.lawExpression = law.parameter1;
			   int k;
			   int size = law.reactsAndMods.size();
			   if(this.hasLocations == true && this.hasOneLocation == false){
				   for(k=0; k<size; k++){
					   if(law.stoichs.get(k) == 1){
						   law.lawExpression = law.lawExpression + "*" + law.reactsAndMods.get(k).speciesName + "." + law.location.locationName ;
					   }
					   else{
						   law.lawExpression = law.lawExpression + "*" + law.reactsAndMods.get(k).speciesName + "." + law.location.locationName + "^" + law.stoichs.get(k)  ;
					   }
				   }
			   }
			   else{
				   for(k=0; k<size; k++){
					   if(law.stoichs.get(k) == 1){
						   law.lawExpression = law.lawExpression + "*" + law.reactsAndMods.get(k).speciesName ;
					   }
					   else{
						   law.lawExpression = law.lawExpression + "*" + law.reactsAndMods.get(k).speciesName + "^" + law.stoichs.get(k)  ;
					   }
				   }
			   }
			   
		   }  
		}
		
		//Controllo che tutte le law usate abbiano expression
		Iterator iterator5 = lawObjectsEff.keySet().iterator();  
		while (iterator5.hasNext()) {  	
		   String key = iterator5.next().toString();
		   if(lawObjectsEff.get(key).isUsed==true && lawObjectsEff.get(key).lawExpression == null){
			   throw new BiopepaException("Error: undefinded expression for kinetic law of " + lawObjectsEff.get(key).lawOf + "'.");
		   }   
		}
		
		//Aggiungo le variabili per il parser matematico nel caso di hasOneLocation == true
		if(this.hasOneLocation == true){
			Iterator iterator7 = speciesList.keySet().iterator();  
			while (iterator7.hasNext()) { 
				String key = iterator7.next().toString();
				NewSpecies species = speciesList.get(key);
				Iterator iterator7a = speciesList.get(key).locationsAccessible.keySet().iterator();  
				while (iterator7a.hasNext()) { 
					String key2 = iterator7a.next().toString();
					NewLocation location = speciesList.get(key).locationsAccessible.get(key2).location;
					evaluator.addConstant(species.speciesName + "." + location.locationName , 0);
					}

				}
		}
		
	}
	
	
	
	
	
	
	
	
	
	
	//DOPO PARSING
	
	public void addInfo2(){
		
		Iterator iterator3 = speciesList.keySet().iterator();  
		while (iterator3.hasNext()) {  	
		   String key = iterator3.next().toString();
		   if(speciesList.get(key).locationsAccessible.size() == 0){
			   
			   //Riporto il valore iniziale in tutte le location accessibili
			   Iterator iterator3a = locationObjects.keySet().iterator();
			   while (iterator3a.hasNext()){	
				   String key2 = iterator3a.next().toString();
				   NewLocation loc = locationObjects.get(key2);
				   speciesList.get(key).addLocationsAccessible(loc);
				   speciesList.get(key).locationsAccessible.get(loc.locationName).initial = speciesList.get(key).speciesInitial;
				   speciesList.get(key).locationsAccessible.get(loc.locationName).upper = speciesList.get(key).speciesUpper;
			   }
			   
		   }	     

		}
		
		
		
		//Sostituisco nei node l'azione "*" con un ArrayList di azioni		
		Iterator iterator4 = nodeList.keySet().iterator();  
		while (iterator4.hasNext()) {  	
		   String key = iterator4.next().toString();
		   ArrayList<ActionEnabled> list = nodeList.get(key).getActions();
		   if(list != null){
			   int i;
			   int size = list.size();
			   for(i=0; i<size; i++){
				   if(list.get(i).actionEnabledName.equals("*")){
					   if(getSpecies(nodeList.get(key).getContent().nodeName) != null){
						   list.remove(i);
						   NewSpecies species = getSpecies(nodeList.get(key).getContent().nodeName);
						   HashMap< String , ActionEnabled > acts = species.getActionsEnabledObjects();
						   Iterator iterator4a = acts.keySet().iterator(); 
						   while(iterator4a.hasNext()){
							   String key2 = iterator4a.next().toString();			   
							   list.add(acts.get(key2));
						   }
						   addCooperations(list);
					   }
			   }
		   }
		   

		}

		}		
	}
	
	
	
	
	
	
	
	
	//ALBERO
	
	public void createTree(){
//		coopActionCheck();
		inheritNodes(rootNode);
	}	
	
	//Controlla che le azioni di cooperazione sia effettivamente action anabled per le specie
	public void coopActionCheck(){
		Iterator iterator3 = nodeList.keySet().iterator();
		while(iterator3.hasNext()){
			String key = iterator3.next().toString();  
			if(getSpecies(nodeList.get(key).getContent().nodeName) != null){
				ArrayList<ActionEnabled> nodeActions = nodeList.get(key).getActions();
				NewSpecies species = getSpecies(nodeList.get(key).getContent().nodeName);
				HashMap< String , ActionEnabled > speciesActions = species.getActionsEnabledObjects();
				if(isContained(nodeActions , speciesActions) == false){
					throw new BiopepaException("Non enabled actions in cooperation set for species '" + species.speciesName + "'.");
				}
				
			}
			
		}
	}
	
	//Verifica che un ArrayList di ActionEnabled sia contenuto in un HashMap di ActionEnabled 
	public boolean isContained(ArrayList<ActionEnabled> list1 , HashMap< String , ActionEnabled> list2){
		boolean bool;
		bool = true;
		int i;
		int size = list1.size();
		for(i=0; i<size; i++){
			if(list2.containsKey(list1.get(i).actionEnabledName) == false){
				bool = false;
			}
		}
		return bool;
	}

	//concatena due hash map di nodi
	public HashMap<String , Node> concNodeList(HashMap<String , Node> list1, HashMap<String , Node> list2){
		HashMap<String , Node> result = new HashMap<String , Node>();
		Iterator iterator1 = list1.keySet().iterator();  
		while (iterator1.hasNext()) {  
		   String key = iterator1.next().toString();  
		   result.put( key , list1.get(key));
		}
		
		Iterator iterator2 = list2.keySet().iterator();  
		while (iterator2.hasNext()) {  
		   String key = iterator2.next().toString();  
		   result.put( key , list2.get(key));
		}
		
		return result;
	}

	//ritorna una hash map con tutti i figli di node
	public HashMap<String , Node> getChildren(Node node) {
		if (  (node.getRightChild() == null) && (node.getLeftChild() == null)  ) {
			HashMap<String , Node> lista = new HashMap<String , Node>();
			lista.put(node.getContent().nodeName, node); 
			return lista;
		}
		
		else{
			if( (node.getRightChild() != null) && (node.getLeftChild() == null) ){
				return getChildren(node.getRightChild());
			}
			if( (node.getLeftChild() != null) && (node.getLeftChild() == null) ){
				return getChildren(node.getLeftChild());
			}
			else{		
				return concNodeList( getChildren(node.getLeftChild()) , getChildren(node.getRightChild()) );
			}

		}
		}
	

	//Per ogni reazione in cooperations aggiunge tutti i nodi coinvolti
	public void inheritNodes(Node node){
//		if(node.getActions() == null){
		if(isRoot(node.getContent().nodeName) == true){	
			if(node.getLeftChild() != null){
					inheritNodes(node.getLeftChild());
				}
			if(node.getRightChild() != null){
					inheritNodes(node.getRightChild());
				}
			}
		else if(node.getActions() == null){}
		else{
			ArrayList<ActionEnabled> acts = node.getActions();
			int actsSize = acts.size();
			int i;
			for(i=0; i<actsSize; i++){
				ActionEnabled act = acts.get(i);
				NewReaction reac = cooperations.get(act.actionEnabledName);
				reac.nodesInvolved = concNodeList(reac.nodesInvolved , getChildren(node));
				if((node.getRightChild() == null) && (node.getLeftChild() == null))
					{}
				else{
					if(node.getLeftChild() != null){
						inheritNodes(node.getLeftChild());
						}
					if(node.getRightChild() != null){
						inheritNodes(node.getRightChild());
						}
				}
			}
		}
	}
	
	
	
	
	
	
	
	

	
	

			
			
	
	
	
	
			
	//*****AUTOMATA METHODS*****	
	
	public void createAutomata(){
		setStepSize();
		createSpeciesAutomata();
		Automaton auto = createFinalAutomaton2(automatonObjects);
		setFinalAutomaton2(auto);
	}
		
	public void setStepSize(){
		Iterator iterator1 = speciesList.keySet().iterator();  		   
		while (iterator1.hasNext()) {  
			 String key = iterator1.next().toString(); 
			 if(speciesList.get(key).hasComponent == true){
				 Iterator iterator1b = speciesList.get(key).getActionsEnabledObjects().keySet().iterator();  		   
					while (iterator1b.hasNext()) {  
						 String key2 = iterator1b.next().toString(); 
						 
					}
			 }
		}
	}

	public void createSpeciesAutomata(){
			Iterator iterator1 = speciesList.keySet().iterator();  		   
			while (iterator1.hasNext()) {  
				 String key = iterator1.next().toString(); 
				 if(speciesList.get(key).hasComponent == true){
					 Iterator iterator1b = speciesList.get(key).locationsAccessible.keySet().iterator();  		   
						while (iterator1b.hasNext()) {  
							 String key2 = iterator1b.next().toString();
								 Automaton newAutomaton;
								 newAutomaton = new Automaton(speciesList.get(key) ,speciesList.get(key).locationsAccessible.get(key2) , this);
								 automatonObjects.put(newAutomaton.getAutoName() , newAutomaton);
								 //System.out.println("put " + newAutomaton.getAutoName());
						}
				 }
			}		
		}
	
	public Automaton createFinalAutomaton2(HashMap<String , Automaton> autoList){
		Automaton finalAuto = new Automaton("System");
		Iterator iterator5 = autoList.keySet().iterator();  		 
		while (iterator5.hasNext()) {  
			String key = iterator5.next().toString();
			   Iterator iterator2d = autoList.get(key).getAutoDiscreteTrans().keySet().iterator();		   
			   while (iterator2d.hasNext()) {  
				   String key2 = iterator2d.next().toString(); 
				   DiscreteTrans trans = autoList.get(key).getAutoDiscreteTrans().get(key2);
				   DiscreteTrans trans2;
				   if(trans.isDisplacement == false){
					   if(finalAuto.autoDiscreteTrans.containsKey(trans.discreteNameWith) == false){
						   finalAuto.autoDiscreteTrans.put(trans.discreteNameWith , trans);
					    }
					  trans2 = finalAuto.autoDiscreteTrans.get(trans.discreteNameWith);
				   }
				   else{
					   if(finalAuto.autoDiscreteTrans.containsKey(trans.discreteName) == false){
						   finalAuto.autoDiscreteTrans.put(trans.discreteName , trans);
					    }
					   trans2 = finalAuto.autoDiscreteTrans.get(trans.discreteName);
				   }
				   
				   
				   //Stabilisco se � continua o discreta
				   if(trans.isContinuous2 == false && trans.isReagOrProd){
					   trans2.isContinuous2 = false;
					   }
				   //Inserisco rate
				   if(trans.isContinuous2 == true){ 
					   trans2.rate = "(" + lawObjectsEff.get(trans.discreteNameWith).lawExpression + ")/" + trans2.location.stepSizeVariableC ;
					   
				   }
				   else{
					   trans2.rate = "(" + lawObjectsEff.get(trans.discreteNameWith).lawExpression + ")/" + trans2.location.stepSizeVariableD ;
					  
				   }
				   
			   }
		}
		return finalAuto;
	}
	
	public void setFinalAutomaton2(Automaton auto){
		   finalAutomaton = automataProduct2(auto , automatonObjects);				
	}
	

	
	public Automaton automataProduct2(Automaton automaton , HashMap<String , Automaton> autoList){
		Automaton finalAuto;
		finalAuto = automaton;
		Iterator iterator2 = autoList.keySet().iterator();  		 
		while (iterator2.hasNext()) {  
			String key = iterator2.next().toString();
			
			   //Aggiungo variabilil
			   Iterator iterator2b = autoList.get(key).getVariables().keySet().iterator();  		   
			   while (iterator2b.hasNext()) {  
				   String key2 = iterator2b.next().toString(); 
				   finalAuto.getVariables().put( key2  , autoList.get(key).getVariables().get(key2));
				   if(this.hasOneLocation == true){
				   }
				   
				}
			   
			   //Aggiungo e completo transizioni discrete con guardie e reset
			   Iterator iterator2c = autoList.get(key).getAutoDiscreteTrans().keySet().iterator();		   
			   while (iterator2c.hasNext()) {  
				   String key2 = iterator2c.next().toString(); 
				   Automaton auto = autoList.get(key);
				   DiscreteTrans trans = autoList.get(key).getAutoDiscreteTrans().get(key2);

				   DiscreteTrans trans2;
				   if(trans.isDisplacement == false){
					   trans2 = finalAuto.autoDiscreteTrans.get(trans.discreteNameWith); 
				   }
				   else{
					   trans2 = finalAuto.autoDiscreteTrans.get(trans.discreteName); 
				   }
				   //Inserisco rate
//				   trans2.rate = "(" + lawObjects.get(trans.discreteName).lawExpression + ")/" + trans2.location.stepSizeVariable ;
				   //GUARDIA
				   if(trans2.isContinuous2 == false){
					   if(trans.isDisplacement == false){
						   if(trans.guard!=null){
							   if( finalAuto.autoDiscreteTrans.get(trans.discreteNameWith).counter1 == 0  ){
								   trans2.guard = trans.guard;
								   finalAuto.autoDiscreteTrans.get(trans.discreteNameWith).counter1++ ;		
								}
								else{
									trans2.guard = trans2.guard + " && " + trans.guard;
								}
						   }
					   }
					   else{
						   if(trans.guard!=null){
							   if( finalAuto.autoDiscreteTrans.get(trans.discreteName).counter1 == 0  ){
								   trans2.guard = trans.guard;
								   finalAuto.autoDiscreteTrans.get(trans.discreteName).counter1++ ;		
								}
								else{
									trans2.guard = trans2.guard + " && " + trans.guard;
								}
						   }
					   }
					   
					   
				   }
				   else if(trans2.isContinuous2 == true){
					   if(trans.isDisplacement == false){
						   if(finalAuto.autoDiscreteTrans.get(trans.discreteNameWith).counter1 == 0){
							   trans2.guard = null;
						   }
						   if(auto.isContinuous() == false){
							   if(trans.guard!=null){
								   if( finalAuto.autoDiscreteTrans.get(trans.discreteNameWith).counter1 == 0){
									   trans2.guard = trans.guard;
									   finalAuto.autoDiscreteTrans.get(trans.discreteNameWith).counter1++ ;		
									}
									else{
											trans2.guard = trans2.guard + " && " + trans.guard;
									}
							   }
						   } 
					   }
					   else{
						   if(finalAuto.autoDiscreteTrans.get(trans.discreteName).counter1 == 0){
							   trans2.guard = null;
						   }
						   if(auto.isContinuous() == false){
							   if(trans.guard!=null){
								   if( finalAuto.autoDiscreteTrans.get(trans.discreteName).counter1 == 0){
									   trans2.guard = trans.guard;
									   finalAuto.autoDiscreteTrans.get(trans.discreteName).counter1++ ;		
									}
									else{
											trans2.guard = trans2.guard + " && " + trans.guard;
									}
							   }
						   }
						   
					   }
					   
					   
				   }
					//RESET
				   if(trans.isDisplacement == false){
					   if( finalAuto.autoDiscreteTrans.get(trans.discreteNameWith).counter2 == 0 &&  trans.reset!=null){
							trans2.reset = trans.reset;
							finalAuto.autoDiscreteTrans.get(trans.discreteNameWith).counter2++ ;		
						}
						else{
							if(trans.reset != null){
								trans2.reset = trans2.reset + "; " + trans.reset;
							}
						}
				   }
				   else{
					   if( finalAuto.autoDiscreteTrans.get(trans.discreteName).counter2 == 0 &&  trans.reset!=null){
							trans2.reset = trans.reset;
							finalAuto.autoDiscreteTrans.get(trans.discreteName).counter2++ ;		
						}
						else{
							if(trans.reset != null){
								trans2.reset = trans2.reset + "; " + trans.reset;
							}
						} 
				   }
					
					   
				   }		   
				}		   
			
		
		finalAuto.autoParameters = parameterObjects;
		return finalAuto;
	}
	

	
	
		
		
	
		
		
		
	//*****OUTPUT*****


	
	
	
	//Automata output
	
	
	
	
	
	
	
	public String automatonString(Automaton automaton){
		String out;
		int autoDiscreteTranSize, j;
		out = "model " + automaton.getAutoName()  + " {" ;
		
		Iterator iterator3 = automaton.autoParameters.keySet().iterator();  
		while (iterator3.hasNext()) {  
		   String key = iterator3.next().toString(); 
		   if(automaton.autoParameters.get(key).isStepSize == true){
			   out = out + "\n param " + automaton.autoParameters.get(key).parameterName + "=" + automaton.autoParameters.get(key).parameterExpression + ";";
		   }
		}

		Iterator iterator1 = automaton.getVariables().keySet().iterator();  
		while (iterator1.hasNext()) {  
		   String key = iterator1.next().toString();  
		   out = out + "\n" + key + "=" + automaton.getVariables().get(key) + ";";
		}
		
		Iterator iterator3a = automaton.autoParameters.keySet().iterator();  
		while (iterator3a.hasNext()) {  
		   String key = iterator3a.next().toString(); 
		   if(automaton.autoParameters.get(key).isSpecParam == true){
			   if(automaton.autoParameters.get(key).isExpression == false){
				   out = out + "\n param " + automaton.autoParameters.get(key).parameterName + "=" + automaton.autoParameters.get(key).parameterExpression + ";";
			   }
			   else if(automaton.autoParameters.get(key).isExpression == true){
				   out = out + "\n expression " + automaton.autoParameters.get(key).parameterName + "=" + automaton.autoParameters.get(key).parameterExpression + ";";
			   }
		   }
		}
		
		Iterator iterator3b = automaton.autoParameters.keySet().iterator();  
		while (iterator3b.hasNext()) {  
		   String key = iterator3b.next().toString(); 
		   if(automaton.autoParameters.get(key).isStepSize == false && automaton.autoParameters.get(key).isSpecParam == false){
			   if(automaton.autoParameters.get(key).isExpression == false){
				   out = out + "\n param " + automaton.autoParameters.get(key).parameterName + "=" + automaton.autoParameters.get(key).parameterExpression + ";";
			   }
			   else if(automaton.autoParameters.get(key).isExpression == true){
				   out = out + "\n expression " + automaton.autoParameters.get(key).parameterName + "=" + automaton.autoParameters.get(key).parameterExpression + ";";
			   }
		   }	   
		}
		
		Iterator iterator2 = automaton.autoDiscreteTrans.keySet().iterator();  
		while (iterator2.hasNext()) {  
		   String key = iterator2.next().toString(); 
		   if(automaton.autoDiscreteTrans.get(key).isContinuous2 == false){
			   if(automaton.autoDiscreteTrans.get(key).isDisplacement == false){
				   out = out + "\n" ;
				   if(this.hasOneLocation == true || automaton.autoDiscreteTrans.get(key).isDisplacement == true){
					   out = out + automaton.autoDiscreteTrans.get(key).discreteName;
				   }
				   else{
					   out = out + automaton.autoDiscreteTrans.get(key).discreteNameWith;
				   }
				   out = out + ":" + "[" ;
				   if(automaton.autoDiscreteTrans.get(key).guard != null){
					   out = out + automaton.autoDiscreteTrans.get(key).guard;
				   }
				   out = out + " :-> ";
				   if(automaton.autoDiscreteTrans.get(key).reset != null){
					   out = out + automaton.autoDiscreteTrans.get(key).reset;
				   }
				   out = out + "]" + "@" + "{" + automaton.autoDiscreteTrans.get(key).rate + "}" + ";" ;	
			   }
			   else{
				   out = out + "\n";
				   if(this.hasOneLocation == true || automaton.autoDiscreteTrans.get(key).isDisplacement == true){
					   out = out + automaton.autoDiscreteTrans.get(key).discreteName;
				   }
				   else{
					   out = out + automaton.autoDiscreteTrans.get(key).discreteNameWith;
				   }
				   out = out + ":" + "[" ;
				   if(automaton.autoDiscreteTrans.get(key).guard != null){
					   out = out + automaton.autoDiscreteTrans.get(key).guard;
				   }
				   out = out + " :-> ";
				   if(automaton.autoDiscreteTrans.get(key).reset != null){
					   out = out + automaton.autoDiscreteTrans.get(key).reset;
				   }
				   out = out + "]" + "@" + "{" + automaton.autoDiscreteTrans.get(key).rate + "}" + ";" ;	
			   }
			   		   
		   }
		   else{
			   if(automaton.autoDiscreteTrans.get(key).isDisplacement == false){
				   out = out + "\n";
				   if(this.hasOneLocation == true){
					   out = out + automaton.autoDiscreteTrans.get(key).discreteName;
				   }
				   else{
					   out = out + automaton.autoDiscreteTrans.get(key).discreteNameWith;
				   }
				   out = out + ":*" + "[" ;
				   if(automaton.autoDiscreteTrans.get(key).guard != null){
					   out = out + automaton.autoDiscreteTrans.get(key).guard;
				   }
				   out = out + " :-> ";
				   if(automaton.autoDiscreteTrans.get(key).reset != null){
					   out = out + automaton.autoDiscreteTrans.get(key).reset;
				   }
				   out = out + "]" + "@" + "{" + automaton.autoDiscreteTrans.get(key).rate + "}" + ";" ;
			   }
			   else{
				   out = out + "\n"; 
				   if(this.hasOneLocation == true){
					   out = out + automaton.autoDiscreteTrans.get(key).discreteName;
				   }
				   else{
					   out = out + automaton.autoDiscreteTrans.get(key).discreteNameWith;
				   }
				   out = out + ":*" + "[" ;
				   if(automaton.autoDiscreteTrans.get(key).guard != null){
					   out = out + automaton.autoDiscreteTrans.get(key).guard;
				   }
				   out = out + " :-> ";
				   if(automaton.autoDiscreteTrans.get(key).reset != null){
					   out = out + automaton.autoDiscreteTrans.get(key).reset;
				   }
				   out = out + "]" + "@" + "{" + automaton.autoDiscreteTrans.get(key).rate + "}" + ";" ;
			   }
			   
			   
		   }
		   
		}	
		out = out + "\n }";
		return out;
	}
	

	

}
